package com.nofx.mydemo.common.log.aspect;

import com.google.common.base.CaseFormat;
import com.nofx.mydemo.common.constant.log.OpType;
import com.nofx.mydemo.common.log.annotation.DebugLog;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author yanyuchi
 * @date 2021-03-20 22:03
 */
@Aspect
@Log4j2
@Component
public class DebugLogAspect {

    @Autowired
    HttpServletRequest request;


    @Around("@annotation(com.nofx.mydemo.common.log.annotation.DebugLog)")
    public Object log(ProceedingJoinPoint pjb) throws Exception{

        Method method = ((MethodSignature)pjb.getSignature()).getMethod();
        DebugLog debugLog = method.getAnnotation(DebugLog.class);

        Object response = null;

        try{
            response = pjb.proceed();
        }catch (Throwable throwable){
            throw new Exception(throwable);
        }

        if(StringUtils.isNotEmpty(debugLog.opItemIdExpression())){
            SpelExpressionParser parser = new SpelExpressionParser();
            Expression expression = parser.parseExpression(debugLog.opItemIdExpression());

            EvaluationContext context = new StandardEvaluationContext();

            Object[] args = pjb.getArgs();

            //获取运行时参数的名称
            LocalVariableTableParameterNameDiscoverer discoverer
                    = new LocalVariableTableParameterNameDiscoverer();
            String[] parameterNames = discoverer.getParameterNames(method);

            if(parameterNames != null){
                for (int i=0;i<parameterNames.length;i++){
                    context.setVariable(parameterNames[i],args[i]);
                }
            }

            //将方法的resp当做变量放到context中,变量名称为该类名转为小写字母开头的驼峰形式
            if(response != null){
                context.setVariable(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL,response.getClass().getSimpleName()),response);
            }

            //解析表达式,获取结果
            String itemId = String.valueOf(expression.getValue(context));

            handle(debugLog.opType(),debugLog.opItem(),itemId);
        }

        return response;
    }

    private void handle(OpType opType,String optItem,String optId){
        log.debug("opType= "+opType.name()+",optItem"+optItem+",optItemId = "+optId);
    }

}
